package com.geeke.sys.controller;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.geeke.admin.common.entity.DataPermission;
import com.geeke.admin.common.service.PermissionService;
import com.geeke.sys.entity.Router;
import com.geeke.sys.entity.Security;
import com.geeke.sys.entity.User;
import com.geeke.sys.service.LoginService;
import com.geeke.sys.service.SecurityService;
import com.geeke.sys.utils.RedisSecurityUtils;
import com.geeke.utils.DateUtils;
import com.geeke.utils.JwtUtils;
import com.geeke.utils.ResultUtil;
import com.geeke.utils.SessionUtils;
import com.geeke.utils.constants.ErrorEnum;

@RestController
@RequestMapping("/auth")
public class AuthController {
    private Logger logger = LoggerFactory.getLogger(AuthController.class);
    private static String LOGIN_LOCKED_MSG = "账户登录失败次数过多，请%d分钟后再登录";

    @Autowired
    private PermissionService permissionService;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private LoginService loginService;

    @Autowired
    private RedisSecurityUtils redisSecurityUtils;

    @Autowired
    private SecurityService securityService;
    
    
    @PostMapping("/token")
    public ResponseEntity<?> getToken(HttpServletRequest request, String loginName, String password) {

        // 检查登录用户是否锁定
        if(redisSecurityUtils.isLock(loginName)) {
            int lockTime = redisSecurityUtils.lock(loginName);
            String msg = String.format(LOGIN_LOCKED_MSG, lockTime);
            return ResponseEntity.ok(ResultUtil.errorJson(ErrorEnum.E_10013, msg));
        }

        //登录
        HttpStatus httpStatus = loginService.authLogin(loginName, password);
        if(HttpStatus.UNAUTHORIZED.equals(httpStatus))	{		//账号密码错误
            int lockTime = redisSecurityUtils.lock(loginName);
            if(lockTime > 0) {  // 失败次数超过安全策略配置的次数，账户暂时锁定
                String msg = String.format(LOGIN_LOCKED_MSG, lockTime);
                return ResponseEntity.ok(ResultUtil.errorJson(ErrorEnum.E_10013, msg));
            }
            return ResponseEntity.ok(ResultUtil.errorJson(ErrorEnum.E_10010));
        } else if(HttpStatus.FORBIDDEN.equals(httpStatus)) {			//账号禁用
            return ResponseEntity.ok(ResultUtil.errorJson(ErrorEnum.E_10011));
        } else if(HttpStatus.SERVICE_UNAVAILABLE.equals(httpStatus)) {  //验证错误
            return ResponseEntity.ok(ResultUtil.errorJson(ErrorEnum.E_10012));
        }

        if(checkExpired()) {
            return ResponseEntity.ok(ResultUtil.errorJson(ErrorEnum.E_10015));
        }

        Map<String, Object> response = getLoginUserInfo(request);

        // 解除登录失败标志
        redisSecurityUtils.unLock(loginName);

        return ResponseEntity.ok(ResultUtil.successJson(response));
    }

    @PostMapping("/loginedtocken")
    public ResponseEntity<?> getLoginedToken(HttpServletRequest request) {
        // 是否登录过
        HttpStatus httpStatus = loginService.authLogin();

        if(!HttpStatus.OK.equals(httpStatus)) {
            return ResponseEntity.ok(ResultUtil.errorJson(ErrorEnum.E_20011));
        }
        Map<String, Object> response = getLoginUserInfo(request);
        return ResponseEntity.ok(ResultUtil.successJson(response));
    }


    /**
     * 登出
     *
     * @return
     */
    @PostMapping("/logout")
    public ResponseEntity<JSONObject> logout() {
        loginService.logout();
        return ResponseEntity.ok(ResultUtil.successJson("退出成功"));
    }

    /**
     * 检查用户账户密码是否过期
     * @return
     */
    private boolean checkExpired() {
        User user = SessionUtils.getUser();
        Security security = securityService.get("1");
        double months = DateUtils.getDistanceMonths(user.getChangePwdDate(), new Date());
        return months >= security.getExpire();
    }

    private Map<String, Object> getLoginUserInfo(HttpServletRequest request) {
        // 得到可访问的router
        User user = SessionUtils.getUser();

        // 用户访问资源权限
        List<String> permissionList = permissionService.listResourcePermissionByUser(user.getId());
        SessionUtils.setUserPermission(permissionList);

        // 用户路由权限
        List<Router> listRouter = permissionService.listRouterPermission(user.getId());

        // 用户数据权限
        List<DataPermission> listDataPermission = permissionService.listDataPermissionByUserId(user.getId());
        
        Map<String, Object> response = new HashMap<String, Object>();
        response.put("userId", user.getId().toString());
        response.put("username", user.getName());
        response.put("loginname", user.getLoginName());

        response.put("isActive", user.getIsActive());
        response.put("changePwdDate", user.getChangePwdDate());

        response.put("company", user.getCompany());
        response.put("department", user.getDepartment());
        response.put("routers", listRouter);
        response.put("dataPermisions", listDataPermission);
        JSONObject json = new JSONObject();
        json.put("host", request.getRemoteHost());
        json.put("userId", user.getId());
        json.put("sessionId", SecurityUtils.getSubject().getSession().getId().toString());
        String token = jwtUtils.createJWT(json.toJSONString());
        response.put("token", token);
        logger.info("User's token = {}", token);
        return response;
    }
    
    
}
